#include "component.h"
#include "comp_camera.h"
#include "device.h"

/* log */
#define CAMERA_LOG(format, ...) OSAL_LOG(C_PURPLE format C_NONE, ##__VA_ARGS__)
#define CAMERA_ASSERT(x)        \
    if ((x) == 0)               \
    {                           \
        OSAL_LOG("ASSERT\r\n"); \
        Device_EnterCritical(); \
        for (;;)                \
            ;                   \
    }

/* 定义事件 */
#define EVT_CAMERA_PROCESS_TX 0x00000001
#define EVT_CAMERA_STANDBY    0x00000002

/* 虚拟设备 */
#define VHW_CAMERA vCAMERA_0 

/* 队列最大长度 */
#define MAX_QUEUE_MSG_LEN 50 

/* 收发缓存队列 */
static SuperQueueHandle_t qCameraRxHandle = NULL;
static SuperQueueHandle_t qCameraTxHandle = NULL;

/* wifi扩展信息 */
static WifiApInfoExt_stu_t wifi_ap_ext_info;

static uint16_t heat_time = 3000;

/* 视频模块的控制标志位 */
static FlagStatus camera_ctrl_flag = SET;


/**
 * @brief 数据接收中断
 *
 * @param dev
 * @param pBuf
 * @param len
 */
static void Camera_Irq_Handler(VirtualHardware_enum_t dev, void *pBuf, uint32_t len)
{
    OSAL_QueueSendToBack(qCameraRxHandle, (void *)pBuf, len);
    OSAL_EventCreateFromISR(COMP_CAMERA);
}

/**
 * @brief 处理接收的数据
 *
 */
static void Camera_ParseRxPacket(void)
{
    uint16_t len = 0;
    while (OSAL_QueueLenght(qCameraRxHandle, &len))
    {
        hi_channel_msg_t *msg = (hi_channel_msg_t *)OSAL_Malloc(len);
        CAMERA_ASSERT(msg != NULL);
        OSAL_QueueReceive(qCameraRxHandle, msg);
        
        if (msg->msg_type == HI_MSGTYPE_HEARTBEAT)
        {
            OSAL_EventSingleCreate(COMP_CAMERA, EVT_CAMERA_STANDBY, heat_time, EVT_PRIORITY_MEDIUM);
        }
        else
        {
            CAMERA_LOG("recv msg, type:%04X, len:%d\r\n", msg->msg_type, len);
            if (msg->msg_type == HI_MSGTYPE_P2P_INFO)
            {
                CAMERA_LOG("p2p_info:%s\r\n", msg->payload);
            }
            else if (msg->msg_type == HI_MSGTYPE_QRCODE_SCAN_REPLY)
            {
                CAMERA_LOG("QRcode: %s\r\n", msg->payload);
            }
            else if (msg->msg_type == HI_MSGTYPE_LCD_CLOSE)
            {
                Device_Write(vPIN_L28, NULL, 0, 0);
            }
            OSAL_MessagePublish(msg, len);
        }
        OSAL_Free(msg);
    }
}

/**
 * @brief 获取wifi的ip/mac/dns等信息
 *
 */
static void Camera_GetWifiExtInfo(void)
{
    if (wifi_ap_ext_info.ip != 0)
    {
        return;
    }

    if (Device_Read(vWIFI_0, &wifi_ap_ext_info, sizeof(wifi_ap_ext_info), 1) == 0)
    {
        hi_channel_msg_t *msg = OSAL_Malloc(sizeof(hi_channel_msg_t) + sizeof(wifi_ap_ext_info));
        CAMERA_ASSERT(msg != NULL);
        msg->msg_type = HI_MSGTYPE_SET_MAC_IP;
        memcpy(msg->payload, &wifi_ap_ext_info, sizeof(wifi_ap_ext_info));
        ErrorStatus ret = OSAL_QueueSendToFront(qCameraTxHandle, msg, sizeof(hi_channel_msg_t) + sizeof(wifi_ap_ext_info));
        CAMERA_LOG("OSAL_QueueSendToFront ret :%d\r\n",ret);
        OSAL_Free(msg);
    }
}

/**
 * @brief 处理TX数据
 *
 */
static void Camera_ProcessTxQueue(void)
{
    uint8_t status = 0;
    uint16_t len = 0;

    //< 判断camera是否上线
    Device_Read(VHW_CAMERA, &status, 1, 0);
    if (status == 0)
    {
        return;
    }

    //< 获取wifi信息
    Camera_GetWifiExtInfo();

    //< 发出TX缓存的数据
    while (OSAL_QueueLenght(qCameraTxHandle, &len))
    {
        void *msg = OSAL_Malloc(len);
        CAMERA_ASSERT(msg != NULL);
        OSAL_QueueReceive(qCameraTxHandle, msg);
        Device_Write(VHW_CAMERA, msg, len, CAMERA_CTRL_SEND_DATA);
        OSAL_Free(msg);
    }
}

/**
 * @brief camera休眠
 * 
 */
static void Camera_Standby(void)
{
    CAMERA_LOG("camera power off\r\n");
    Device_Write(VHW_CAMERA, NULL, 0, CAMERA_CTRL_PWR_OFF);
    memset(&wifi_ap_ext_info, 0, sizeof(wifi_ap_ext_info));
    OSAL_SetTaskStatus(TASK_STA_NORMAL);
    camera_ctrl_flag = RESET;
}

/**
 * @brief 处理邮箱消息
 *
 * @param buf
 * @param len
 */
static void Camera_ProcessMbox(void *buf, uint16_t len)
{
    hi_channel_msg_t *pmsg = (hi_channel_msg_t *)buf;
    /* LCD关命令如果是休眠状态，不处理 */
    if (pmsg->msg_type == HI_MSGTYPE_LCD_CTRL && camera_ctrl_flag == RESET)
    {
        hi_lcd_param_stu_t *lcd_param = (hi_lcd_param_stu_t*)pmsg->payload;
        if (lcd_param->ctrl == 2)
        {
            CAMERA_LOG("lcd is closed\r\n");
            return;
        }
    }

    if (pmsg->msg_type == HI_MSGTYPE_LCD_CTRL)
    {
        hi_lcd_param_stu_t *msg = (hi_lcd_param_stu_t *)pmsg->payload;
        if (msg->ctrl != 2)/* 如果是关屏命令不开屏幕按键白灯 */
        {
            Device_Write(vPIN_L28, NULL, 0, 1);
        }
    }

    ErrorStatus ret = OSAL_QueueSendToBack(qCameraTxHandle, buf, len);
    CAMERA_LOG("OSAL_QueueSendToBack ret :%d\r\n",ret);
    OSAL_EventSingleCreate(COMP_CAMERA, EVT_CAMERA_STANDBY, heat_time, EVT_PRIORITY_MEDIUM);
    OSAL_SetTaskStatus(TASK_STA_ACTIVE);

    switch (pmsg->msg_type)
    {
    case HI_MSGTYPE_SET_HEARTBEAT_TIME:
    {
        uint8_t time = *(pmsg->payload);
        heat_time = time *1000;
        OSAL_EventSingleCreate(COMP_CAMERA, EVT_CAMERA_STANDBY, heat_time, EVT_PRIORITY_MEDIUM);  
        CAMERA_LOG("recv msg:HI_MSGTYPE_SET_HEARTBEAT_TIME:%u\r\n",time);
    }
        break;

    case HI_MSGTYPE_UPLOAD_PICTURE:
    case HI_MSGTYPE_START_QRCODE_SCAN:
    case HI_MSGTYPE_LCD_CTRL:
    case HI_MSGTYPE_START_AV_TALK:
    case HI_MSGTYPE_START_STORAGE:
    case HI_MSGTYPE_SET_FILL_LIGHT:
        Device_Write(VHW_CAMERA, NULL, 0, CAMERA_CTRL_SENSOR_PWR_ON);
        break;

    default:
        Device_Write(VHW_CAMERA, NULL, 0, CAMERA_CTRL_HOST_PWR_ON);
        break;
    }
    camera_ctrl_flag = SET;
}

/**
 * @brief 接收应用层发来的邮箱
 *
 */
static void Camera_ProcessRecvMbox(void)
{
    uint16_t len = 0;
    while (OSAL_MboxLenght(&len))
    {
        void *buffer = OSAL_Malloc(len);
        CAMERA_ASSERT(buffer != NULL);
        OSAL_MboxAccept(buffer);
        Camera_ProcessMbox(buffer, len);
        OSAL_Free(buffer);
    }
}

/**
 * @brief camera组件初始化
 *
 */
static void Camera_Init(void)
{
    CAMERA_LOG("camera Init\r\n");
    if (qCameraRxHandle == NULL && qCameraTxHandle == NULL)
    {
        qCameraRxHandle = OSAL_QueueCreate(MAX_QUEUE_MSG_LEN);
        qCameraTxHandle = OSAL_QueueCreate(MAX_QUEUE_MSG_LEN);
        Device_RegisteredCB(VHW_CAMERA, Camera_Irq_Handler);
        OSAL_EventRepeatCreate(COMP_CAMERA, EVT_CAMERA_PROCESS_TX, 10, EVT_PRIORITY_MEDIUM);
    }
}

/**
 * @brief camera任务
 *
 * @param event
 * @return uint32_t
 */
static uint32_t Camera_Task(uint32_t event)
{
    /* 系统启动事件 */
    if (event & EVENT_SYS_START)
    {
        CAMERA_LOG("camera task start\r\n");
        Camera_Init();
        return (event ^ EVENT_SYS_START);
    }

    /* camera逻辑处理 */
    if (event & EVT_CAMERA_PROCESS_TX)
    {
        Camera_ProcessTxQueue();
        return (event ^ EVT_CAMERA_PROCESS_TX);
    }

    /* 系统邮箱事件 */
    if (event & EVENT_SYS_MBOX)
    {
        Camera_ProcessRecvMbox();
        return (event ^ EVENT_SYS_MBOX);
    }

    /* 中断事件 */
    if (event & EVENT_SYS_ISR)
    {
        Camera_ParseRxPacket();
        return (event ^ EVENT_SYS_ISR);
    }

    /* standby */
    if (event & EVT_CAMERA_STANDBY)
    {
        Camera_Standby();
        return (event ^ EVT_CAMERA_STANDBY);
    }

    /* 休眠事件 */
    if (event & EVENT_SYS_SLEEP)
    {
        CAMERA_LOG("camera task sleep\r\n");
        OSAL_QueueReset(qCameraTxHandle);
        OSAL_QueueReset(qCameraRxHandle);
        Device_Write(VHW_CAMERA, NULL, 0, CAMERA_CTRL_PWR_OFF);
        memset(&wifi_ap_ext_info, 0, sizeof(wifi_ap_ext_info));
        return (event ^ EVENT_SYS_SLEEP);
    }
}
COMPONENT_TASK_EXPORT(COMP_CAMERA, Camera_Task, 0);
char import_kos_camera;
